package com.bright.cwduijie.duijie.service;

import com.bright.cwduijie.common.util.StringUtil;
import com.bright.cwduijie.duijie.enums.DataApi;
import com.bright.cwduijie.duijie.pojo.command.DuijieCommand;
import com.bright.cwduijie.duijie.service.impl.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 工厂类
 */

@Component
@RequiredArgsConstructor
@Slf4j
public class ApiServiceFactory {

    private final ApiAccSetServiceImpl accSet;
    private final ApiAccCodeServiceImpl accCode;
    private final ApiAssistCodeServiceImpl assistCode;
    private final ApiAssistCodeTypeServiceImpl assistCodeType;
    private final ApiVoucherServiceImpl voucher;
    private final ApiBalanceServiceImpl balance;
    private final ApiCreditPublishServiceImpl creditPublish;
    private final ApiDebtPublishServiceImpl debtPublish;

    private final ApiBioAssetsServiceImpl bioAssets;
    private final ApiImmaterialAssetsServiceImpl immaterialAssets;
    private final ApiInventoryAssetsServiceImpl inventoryAssets;
    private final ApiCollectiveLandServiceImpl collectiveLand;
    private final ApiContractServiceImpl contract;
    private final ApiCustomAssetCodeServiceImpl customAssetCode;
    private final ApiDayBooksServiceImpl dayBooks;
    private final ApiFixedAssetsDepreciationLogServiceImpl depreciationLogs;
    private final ApiFixedAssetsHandleLogServiceImpl handleLogs;
    private final ApiFixedAssetsInfoChangeServiceImpl infoChanges;
    private final ApiFixedAssetsValueChangeServiceImpl valueChanges;
    private final ApiFixedAssetsServiceImpl fixedAssets;
    private final ApiMonthlySettlementServiceImpl monthlySettlement;
    private final ApiSendFileServiceImpl sendFileService;

    // 冲洗凭证的服务 注意：这个不是常规接口 只实现getData和sendData方法 其他不可用
    private final ApiFlushVoucherServiceImpl flushVoucherService;

    /**
     * 获取所有需要对接的接口
     * 注意：返回的列表是Arrays.asList 不可追加数据
     * @param duijieCommand
     * @return
     */
    public List<AbstractApiService<?>> getNeedDuijieApis(DuijieCommand duijieCommand) {
        List<String> serviceCodes = duijieCommand.getServiceCodes();
        if (serviceCodes.size() == 0) {
            // 如果没指定 就给全部接口
            return Arrays.asList(accSet, accCode, voucher, dayBooks, contract, fixedAssets,
                    monthlySettlement, // v1.6.12 月结放到凭证后面 负债表前面推
                    balance, creditPublish, debtPublish,
                    depreciationLogs, handleLogs, infoChanges, valueChanges,
                    assistCode, assistCodeType, bioAssets, collectiveLand, customAssetCode, immaterialAssets, inventoryAssets);


        }
        return getApisByServiceCode(serviceCodes);
    }

    /**
     * 获取不按月份推送的接口
     * @param duijieCommand
     * @return
     */
    public List<AbstractApiService<?>> getNeedDuijieApisNoMonths(DuijieCommand duijieCommand) {
        List<String> serviceCodes = duijieCommand.getServiceCodes();
        if (serviceCodes.size() == 0) {
            // 如果没指定 就给全部不按月份的接口
            return Arrays.asList(accSet, accCode, dayBooks, contract, fixedAssets, infoChanges, valueChanges,
                    assistCode, assistCodeType, bioAssets, collectiveLand, customAssetCode, immaterialAssets, inventoryAssets);
        }
        return getApisByServiceCode(serviceCodes);
    }

    public List<AbstractApiService<?>> getApisByServiceCode(List<String> serviceCodes) {
        List<AbstractApiService<?>> result = new ArrayList<>();
        for (String serviceCode : serviceCodes) {
            // v1.6.8 文件附件上传
            if (StringUtil.equals(serviceCode, "DJ_FILE")) {
                result.add(sendFileService);
                continue;
            }

            Optional<DataApi> optionalDataApi = DataApi.ofOptional(serviceCode);
            if (!optionalDataApi.isPresent()) {
                log.error("查不到指定接口，跳过：" + serviceCode);
                continue;
            }
            DataApi dataApi = optionalDataApi.get();

            switch (dataApi) {
                case ACC_SET:
                    result.add(accSet);
                    break;
                case ACC_CODE:
                    result.add(accCode);
                    break;
                case ASSIST_CODE:
                    result.add(assistCode);
                    break;
                case ASSIST_CODE_TYPE:
                    result.add(assistCodeType);
                    break;
                case BALANCE:
                    result.add(balance);
                    break;
                case BIO_ASSETS:
                    result.add(bioAssets);
                    break;
                case COLLECTIVE_LAND:
                    result.add(collectiveLand);
                    break;
                case CONTRACT:
                    result.add(contract);
                    break;
                case CREDIT_PUBLISH:
                    result.add(creditPublish);
                    break;
                case CUSTOM_ASSET_CODE:
                    result.add(customAssetCode);
                    break;
                case DAY_BOOKS:
                    result.add(dayBooks);
                    break;
                case DEBT_PUBLISH:
                    result.add(debtPublish);
                    break;
                case FIXED_ASSETS_DEPRECIATION_LOG:
                    result.add(depreciationLogs);
                    break;
                case FIXED_ASSETS:
                    result.add(fixedAssets);
                    break;
                case FIXED_ASSETS_HANDLE_LOG:
                    result.add(handleLogs);
                    break;
                case IMMATERIAL_ASSETS:
                    result.add(immaterialAssets);
                    break;
                case FIXED_ASSETS_INFO_CHANGE:
                    result.add(infoChanges);
                    break;
                case INVENTORY_ASSETS:
                    result.add(inventoryAssets);
                    break;
                case MONTHLY_SETTLEMENT:
                    result.add(monthlySettlement);
                    break;
                case FIXED_ASSETS_VALUE_CHANGE:
                    result.add(valueChanges);
                    break;
                case VOUCHER:
                    result.add(voucher);
                    break;

                default:
                    break;
            }

        }
        return result;
    }

    public List<AbstractApiService<?>> getDuijieApisByBatchKey(String batchKey) {
        // 分批推送的工厂方法

        switch (batchKey) {
            // 20240720 批次之间的具体顺序在SystemConstants类的nextBatchMap里指定
            case "1":
            case "km":
                // 第一批数据
                return Arrays.asList(accSet, accCode);

            case "2":
            case "pz":
                return Collections.singletonList(voucher);

            case "3":
            case "dcf":
                return Arrays.asList(dayBooks, contract, fixedAssets, bioAssets, inventoryAssets, immaterialAssets);

            case "4":
            case "bdc":
                return Arrays.asList(balance, debtPublish, creditPublish, handleLogs, depreciationLogs, infoChanges, valueChanges);

//            case "fzhslx":
//                // 辅助核算类型
//                return Collections.singletonList(assistCodeType);
//
//            case "fzhsxm":
//                // 辅助核算项目
//                return Collections.singletonList(assistCode);

            // v1.6.7 获取除月结外所有按月份推送的接口
            case "yfsj":
                return Arrays.asList(voucher, balance, creditPublish, debtPublish, depreciationLogs, handleLogs);

            case "zt":
                return Collections.singletonList(accSet);

            case "onlykm":
                return Collections.singletonList(accCode);

            // v1.6.9 冲洗凭证
            case "cxpz":
                return Collections.singletonList(flushVoucherService);

            case "5":
            case "yj":
            case "yj1":
                // 月结 必定是最后一批
                return Collections.singletonList(monthlySettlement);

            default:
                log.debug("不存在该批次：" + batchKey);
                return Collections.emptyList();
        }
    }

    /**
     * 获取账套对接接口
     * @return
     */
    public ApiAccSetServiceImpl getAccSetService() {
        return accSet;
    }

    public ApiMonthlySettlementServiceImpl getMonthlySettlementService() {
        return monthlySettlement;
    }

    public ApiVoucherServiceImpl getVoucherService() {
        return voucher;
    }

    public ApiFixedAssetsServiceImpl getFixedAssetsService() {
        return fixedAssets;
    }

    public ApiSendFileServiceImpl getSendFileService() {
        return sendFileService;
    }

    public ApiFlushVoucherServiceImpl getFlushVoucherService() {
        return flushVoucherService;
    }

}
